﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Gridify.Controllers;

namespace Gridify
{
    public class GridData<T> : IGridData
    {
        public GridData(IList<T> items)
        {
            Items = items;
        }

        public Guid Id { get; set; }
        public IList<T> Items { get; set; }
        public int PageSize { get; set; }
        public string ViewTemplateName { get; set; }

        public int TotalPages
        {
            get { return Items.Count / PageSize; }
        }

        public ItemsInfo GetItems(int page, IEnumerable<ColumnFilter> filters, string sortBy, int sortDir)
        {
            IEnumerable<T> result = string.IsNullOrWhiteSpace(sortBy)
                                        ? (IEnumerable<T>)Items
                                        : sortDir == 1
                                              ? Items.OrderBy(i => GetColumnValue(i, sortBy)) 
                                              : Items.OrderByDescending(i => GetColumnValue(i, sortBy));

            if(filters != null)
                foreach (var filter in filters.Where(f => !string.IsNullOrWhiteSpace(f.Value)))
                {
                    var column = filter.Column;
                    var value = filter.Value;
                    result = result.Where(i => GetColumnValue(i, column).IndexOf(value, StringComparison.InvariantCultureIgnoreCase) != -1);
                }

            return new ItemsInfo
                       {
                           Items = result.Skip(PageSize*page).Take(PageSize),
                           TotalPages = result.Count() / PageSize
                       };
        }

        private static string GetColumnValue(T item, string column)
        {
            var type = typeof (T);
            var propertyInfo = type.GetProperty(column, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
            
            return propertyInfo != null
                       ? GetValueString(propertyInfo.GetValue(item, null))
                       : string.Empty;
        }

        private static string GetValueString(object value)
        {
            return value != null
                       ? value.ToString()
                       : string.Empty;
        }
    }
}